<?php

namespace maotool\aop;

use maotool\core\Container;
use maotool\exception\RuntimeException;
use maotool\object\ObjUtil;
use maotool\object\ReflectionUtil;

/**
 * 切面代理
 */
class ContainerProxyClass
{
    /**
     * @var Container
     */
    protected $container_5698e30a3e171b662711d3916069e9a;

    /**
     * @var string
     */
    protected $instance_id_5698e30a3e171b662711d3916069e9a;

    /**
     * @var ProxyClassCallback
     */
    protected $callback_5698e30a3e171b662711d3916069e9a;

    /**
     * @param Container $container
     * @param string $instanceId
     * @param ProxyClassCallback $callback
     */
    public function __construct(&$container, $instanceId, $callback)
    {
        $this->container_5698e30a3e171b662711d3916069e9a = $container;
        $this->instance_id_5698e30a3e171b662711d3916069e9a = $instanceId;
        $this->callback_5698e30a3e171b662711d3916069e9a = $callback;
    }

    /**
     * @param string $name
     * @param array $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        $instance = $this->container_5698e30a3e171b662711d3916069e9a->getInstanceById($this->instance_id_5698e30a3e171b662711d3916069e9a);
        if (!$instance->init) {
            $log_time_start = microtime(true);
            $instance->instance = ReflectionUtil::instance($instance->concrete, $instance->vars);
            $instance = Container::autowired($instance);
            if (ObjUtil::isNotNull($instance->construct)) {
                $construct = $instance->construct;
                $construct($instance->vars, $instance->instance);
            }
            $instance->init = true;
//            \maotool\log\Console::debug('框架容器 -> 初始化 ' . $instance->class . ' 加载用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
        }
        $param = $this->callback_5698e30a3e171b662711d3916069e9a->callBefore($instance->instance, $name, $arguments);
        $result = ReflectionUtil::method([$instance->instance, $name], $param);
        return $this->callback_5698e30a3e171b662711d3916069e9a->callAfter($instance->instance, $name, $result);
    }

    /**
     * @param string $name
     * @return mixed
     */
    public function __get($name)
    {
        $instance = $this->container_5698e30a3e171b662711d3916069e9a->getInstanceById($this->instance_id_5698e30a3e171b662711d3916069e9a);
        if (!$instance->init) {
            $log_time_start = microtime(true);
            $instance->instance = ReflectionUtil::instance($instance->concrete, $instance->vars);
            $instance = Container::autowired($instance);
            if (ObjUtil::isNotNull($instance->construct)) {
                $construct = $instance->construct;
                $construct($instance->vars, $instance->instance);
            }
            $instance->init = true;
//            \maotool\log\Console::debug('框架容器 -> 初始化 ' . $instance->class . ' 加载用时：' . (microtime(true) - $log_time_start) . ' 秒。');
        }
        return $this->callback_5698e30a3e171b662711d3916069e9a->get(
            $name,
            ReflectionUtil::getProperty($instance, $name)
        );
    }

    /**
     * @param string $name
     * @param $value
     * @return void
     */
    public function __set($name, $value)
    {
        $instance = $this->container_5698e30a3e171b662711d3916069e9a->getInstanceById($this->instance_id_5698e30a3e171b662711d3916069e9a);
        if (!$instance->init) {
            $log_time_start = microtime(true);
            $instance->instance = ReflectionUtil::instance($instance->concrete, $instance->vars);
            $instance = Container::autowired($instance);
            if (ObjUtil::isNotNull($instance->construct)) {
                $construct = $instance->construct;
                $construct($instance->vars, $instance->instance);
            }
            $instance->init = true;
//            \maotool\log\Console::debug('框架容器 -> 初始化 ' . $instance->class . ' 加载用时：' . (microtime(true) - $log_time_start) . ' 秒。');
        }
        ReflectionUtil::property($instance->instance,
            $name,
            $this->callback_5698e30a3e171b662711d3916069e9a->set($name, $value));
    }

}